package io.elegant.widgets

import android.net.Uri
import android.view.View
import android.view.ViewGroup
import com.google.protobuf.Any
import io.elegant.sessions.widgets.WidgetFileUploaderSession
import io.elegant.toActivity
import io.elegant.toAny
import io.elegant.toStringValue
import io.elegant.upload
import kotlinx.coroutines.CoroutineScope
import okhttp3.OkHttpClient
import kotlin.reflect.KClass

class FileUploaderWidget<T: View>(
    private val session: WidgetFileUploaderSession,
    private val group: ViewGroup,
    private val cs: CoroutineScope
): BaseTextWidget<T>(session, group, cs) {
    private var mimeType = "*/*"
    private var file: Uri? = null
    private var client: OkHttpClient? = null

    override fun create(clazz: KClass<T>, sessionId: Long, futureId: Long, vararg argv: Any) {
        super.create(clazz, sessionId, futureId, *argv)
        client = OkHttpClient
            .Builder()
            .build()
        view?.setOnClickListener {
            group
                .context
                .toActivity()
                ?.selectFile(mimeType) {
                    file = it
                    session.setFile(it)
                }
        }
    }

    override fun destroy() {
        file = null
        client = null
        super.destroy()
    }
    override fun onReceive(name: String, sessionId: Long, futureId: Long, vararg argv: Any): Boolean {
        if (when (name) {
                "getMimeType" -> getMimeType(sessionId, futureId)
                "setMimeType" -> setMimeType(*argv)
                "getFilename" -> getFilename(sessionId, futureId)
                "upload" -> upload(sessionId, futureId, *argv)
                else -> null
        } == null)
            return super.onReceive(name, sessionId, futureId, *argv)
        return true
    }
    private fun getMimeType(sessionId: Long, futureId: Long) {
        onGetMimeType(mimeType.toAny(), sessionId, futureId)
    }
    private fun onGetMimeType(type: Any, sessionId: Long, futureId: Long) = session.apply {
        sendAction("onGetMimeType", sessionId, futureId, type)
    }
    private fun setMimeType(vararg argv: Any) {
        this.mimeType = argv[0].toStringValue()
    }
    private fun getFilename(sessionId: Long, futureId: Long) {
        if (file == null)
            throw Exception("You have not selected a file yet.")
        val filename = file?.lastPathSegment
        onGetFilename(filename.toAny(), sessionId, futureId)
    }
    private fun onGetFilename(filename: Any, sessionId: Long, futureId: Long) = session.apply {
        sendAction("onGetFilename", sessionId, futureId, filename)
    }
    private fun upload(sessionId: Long, futureId: Long, vararg argv: Any) {
        val url = argv[0].toStringValue()
        val file = this.file ?: throw Exception("You have not selected a file yet.")
        val stream = group
            .context
            .contentResolver
            .openInputStream(file)
            ?: throw Exception("There is a problem with the current audio file and it cannot be uploaded.")
        client?.upload(session, cs, argv[1], stream, mimeType, file.lastPathSegment, url) {
            if(it == null) onUpload(true.toAny(), sessionId, futureId)
            else session.apply {
                it.sendError(sessionId, futureId)
            }
        }
    }
    private fun onUpload(result: Any, sessionId: Long, futureId: Long) = session.sendAction("onUpload", sessionId, futureId, result)
}